package cn.echoparrot.domain.service;

import cn.echoparrot.domain.entity.DataFile;
import cn.echoparrot.domain.entity.Dataset;
import cn.echoparrot.domain.entity.FileInfo;
import cn.echoparrot.domain.entity.Segment;
import cn.echoparrot.domain.vo.NewDataset;

import java.io.IOException;
import java.nio.file.Path;
import java.util.List;

/**
 * 知识库的向量存储
 * 将底层的一些细节屏蔽，对上层提供更友好的一些接口。
 * 特别是关于Document 哪些是content，哪些是metadata， 如何构建FilterExpression。
 * 只有neo4j的企业版才支持Single Instance Multiple Databases特性。
 * 这些都需要在此实现类内处理。
 */
public interface DatasetService {

    /**
     * 创建一个知识库
     * 原始文件内容不入库，保存至本地目录。
     * 本地目录使用的是知识库的名称，不是知识库的ID。
     * 原始文件向量化后的内容保存至仓库，用于大模型的理解。
     * 需要注意文件编码、服务器编码设置。
     *
     * @param dataset 创建的参数
     * @return 知识库实体信息
     */
    Dataset create(NewDataset dataset, Integer userId, int dimensions);

    Dataset update(Dataset dataset);

    /**
     * 删除知识库。
     * 删除知识库时，会删除知识库的索引与本地目录。但如果还有文件存在，则会抛出异常。
     * 用户实际操作时需要先删除文件，才能删除知识库，这是为了防止误操作影响太大。
     * @param datasetId 知识库ID
     * @return 是否成功删除
     */
    int delete(Long datasetId) throws IOException;

    /**
     * 列出所有知识库
     * @return
     */
    List<Dataset> listDatasets();

    /**
     * 获得某个指定知识库的上传文档目录
     * @param datasetName 知识库名字，可支持中文名字
     */
    Path uploadPath(Integer userId,String datasetName,String fileName);

    /**
     * 获得某个指定知识库存储文件片段的目录
     * @param datasetName
     * @param fileName
     * @return
     */
    Path segmentPath(Integer userId, String datasetName,String fileName);

    /**
     * 列出指定知识库所有已上传的文件信息。
     * 文件的原始内容不存储进neo4j库，文件内容存储在文件系统里。
     * neo4j只存储：对外：文件名、文件上传时间、文件大小；不对外：md5值，文件类型，切分的片段等信息。
     *
     * @return 文件信息
     * @throws IOException
     */
    List<FileInfo> listUploads(Integer userId, String datasetName) throws IOException;

    List<String> supportedFileTypes();

    default boolean isSupportive(String filenameExtension){
        return supportedFileTypes().contains(filenameExtension);
    }

    void delete(Long datasetId, String[] filenames) throws IOException;

    int addFile(Long datasetId, DataFile file);

    List<Segment> similaritySearch(String indexName, int topK, float[] embeddingValue, double threshold);
}